const fs = require('fs');
const path = require("path");
const xlsx = require('node-xlsx');
const jsonToLua = require("json_to_lua");

/**
 * 支持的数据类型
 */
 const DataType = {
    Number: 'Number',
    String: 'String',
    Boolean: 'Boolean',
    ID: 'ID',// 表格没有 ID类型 按照数组储存，有ID类型的，按照map储存
}
/**
 * 导出的格式
 */
const ToType = {
    json: "json",
    lua: "lua",
}

var argv = process.argv;
var xlsxPath = argv[2] || "./xlsx";
var toPath = argv[3] || "./json";
var toType = argv[4] || "json";

parseXlsxList(xlsxPath, toPath, toType);

/**
 * 根据excel的路径导出指定格式的数据到指定的路径
 * @param {string} xlsxPath excel路径
 * @param {string} toPath 导出数据路径
 * @param {string} toType 导出数据格式
 */
function parseXlsxList(xlsxPath, toPath, toType) {
    var xlsxList = getListSync(xlsxPath, [".xlsx"])
    for (var i = 0; i < xlsxList.length; i++) {
        const xlsxPath = xlsxList[i];
        parseXlsx(xlsxPath, toPath, toType);
    }
}

/**
 * 转换一个表格文件
 * @param {string} xlsxPath 
 */
function parseXlsx(xlsxPath, toPath, toType) {
    var xlsxJson = xlsx.parse(xlsxPath);
    for (var i = 0; i < xlsxJson.length; i++) {
        var sheet = xlsxJson[i];
        var json = convertSheet(sheet.data);
        var content = null;
        var ename = ".json"
        let fileName = path.basename(xlsxPath, path.extname(xlsxPath));
        if (toType == ToType.json) {
            content = JSON.stringify(json);
        }
        else if (toType == ToType.lua) {
            content = jsonToLua.jsObjectToLuaPretty(json, 1);
            content = "local " + fileName + " = " + content;
            ename = ".lua"
        }
        else {
            console.error("倒出类型不存在")
        }

        writeFileSync(toPath + "/" + fileName + ename, content);
    }
}

/**
 * 转换一个表格 sheet
 * @param {any[]} sheetData 
 */
function convertSheet(sheetData) {
    var schema = {};
    var notesArr = sheetData[0];
    var typeArr = sheetData[1];
    var keyArr = sheetData[2];
    var obj = {}
    for (let i = 3; i < sheetData.length; i++) {
        const item = sheetData[i];
        let newObj = {};
        let idKey = null;
        for (let j = 0; j < item.length; j++) {
            var type = typeArr[j];

            let key = keyArr[j].toLowerCase();
            const element = item[j];
            var value = convertItem(element, type);
            newObj[key] = value;
            if (idKey == null && type == DataType.ID) {
                idKey = value;
            }
        }

        if (idKey != null) {
            obj[idKey] = newObj;
        }
        else {
            arr.push(newObj);
        }
    }
    return obj;
}

/**
 * 转换一个数据
 * @param {*} item 
 * @param {*} type 
 * @returns 
 */
function convertItem(item, type) {
    var value = null;
    if (DataType.String === type) {
        value = item ? String(item).replace('\\n', '\n') : ""; // excel里 \n 表示两个字符'\','n', 代码里 \n 表示一个字符 换行符 这里需要单独处理
    } else if (DataType.Number === type) {
        value = item ? Number(item) : 0;
    } else if (DataType.Boolean === type) {
        value = toBoolean(item);
    } else if (DataType.ID === type) {
        value = item ? String(item) : '';
    } else if (-1 !== type.indexOf('Array')) {
        value = converArrayItem(item, type);
    }
    return value;
}

/**
 * 转换一个数据列表
 * @param {*} item 
 * @param {*} type 
 * @returns 
 */
function converArrayItem(item, type) {
    let arr = []
    let newType = type.replace('Array', '');
    if (item == null) {
        return arr
    }
    let splitArr = item.toString().split('|');
    splitArr = splitArr.filter(s => s !== '');

    for (let index = 0; index < splitArr.length; index++) {
        var element = splitArr[index];
        var value = convertItem(element, newType)
        arr.push(value)
    }

    return arr;
}

/**
 * 转换bool
 * @param {*} item 
 * @returns 
 */
function toBoolean(item) {
    if ('string' === typeof (item)) {
        let lower = item.toLocaleLowerCase();
        if (lower === 'true') {
            return true;
        } else {
            return false;
        }
    }
    return item;
}

/**
 * 同步获取指定目录 指定后缀文件列表
 * @param {string} rootPath 目录
 * @param {string[]} extensions 后缀列表
 * @param {string[]} listArr 列表 默认不填写 递归回掉使用
 * @returns 
 */
function getListSync(rootPath, extensions, listArr = []) {
    var files = fs.readdirSync(rootPath);

    for (let i = 0, len = files.length; i < len; i++) {
        const fileName = files[i]; // 文件 文件夹 名字
        let filePath = rootPath + "/" + fileName;  // 路径
        var info = fs.statSync(filePath);
        if (info.isDirectory()) {
            getListSync(filePath, extensions, listArr);
        }
        else {
            let extname = path.extname(filePath);
            if (extensions.indexOf(extname) < 0) continue;
            listArr.push(filePath);
        }

    }
    return listArr;
}

/**
 * 同步写入给定内容。它还会创建必要的父目录。
 * @param {string} filePath 文件路径
 * @param {string | NodeJS.ArrayBufferView} content 文件
 * @param {string} options 参数
 */
function writeFileSync(filePath, content, options = "utf-8") {
    makeTreeSync((path.dirname(filePath)));
    fs.writeFileSync(filePath, content, options);
}

/**
 * 递归创建目录 同步方法
 * @param {string} dirname 目录
 * @returns 
 */
function makeTreeSync(dirname) {
    if (fs.existsSync(dirname)) {
        return true;
    } else {
        if (makeTreeSync(path.dirname(dirname))) {
            fs.mkdirSync(dirname);
            return true;
        }
    }
}